#!/usr/local/bin/python

#-------------------------------------------------------------------------------
# Name:        advbackup
# Purpose:     To backup and manage storage of servers.
#
# Author:      Donald L Talbert , www.bwhgaming.com
#
# Created:     29/09/2012
# Copyright:   (c) Donald L Talbert 2012
# Licence:     MIT
#-------------------------------------------------------------------------------


from shutil import copytree, ignore_patterns, make_archive, rmtree
from time import sleep

import logging
import datetime
import os

import readconfig
lc = readconfig.ReadConfig()



def copyTempDir():
	"""
	Creates a temporary directory to make an archive from, we do this
	to take advantage of the ignore_patterns function from shutils to
	sort out files we do not want.
	"""
	global src
	global dst
	global toIgnore
	
	logging.info("Starting TempFile Copy")
	try:
		copytree(src, dst, ignore=ignore_patterns(toIgnore)) # Fix to accept multiple values
	except:
		return False
	logging.info("Ending TempFile Copy")
	return True
	

def makeArchive():
	"""
	Creates an archive from the temporary directy.
	"""
	global dst
	global archiveType
	
	archiveName = buildArchiveName()
	
	logging.info("Starting Archive")
	make_archive(archiveName, archiveType, dst)
	logging.info("Finished Archive")
	

def cleanUp():
	"""
	Removes the temporary directory we created to create an archive.
	"""
	global src
	global dst
	
	logging.info("Removing: " + dst)
	rmtree(dst)
	logging.info("Finished Removing: " + dst)


def getTime():
	"""
	Returns the current time formatted in a human friendly way as a
	string to insert to the filename of a backup.
	"""
	now = datetime.datetime.now()
	time = str(now.date()) + "_" + str(now.hour) + "h-" + str(now.minute) + 'm'

	return time
	
def convertHoursToSeconds():
	"""
	Converts the hour value from the config to seconds for time.sleep
	compatablity.
	"""
	global timeBetweenBackups
	
	seconds = int(timeBetweenBackups) * 3600
	
	return int(seconds)
	
def NumExistingBackups():
	"""
	returns the number of existing backups.
	"""
	global archiveDir
	
	numBackups = len(os.listdir(archiveDir))
	return int(numBackups)


def OldestBackup():
	"""
	Returns the oldest backup file.
	"""
	global archiveDir
	
	backupsList = os.listdir(archiveDir)
	temp = []
	for backupFile in backupsList:
		archiveName = os.path.join(archiveDir, backupFile)
		temp.append([os.stat(archiveName).st_ctime, backupFile])

	temp2 = sorted(temp, reverse = False, key=lambda test: test[0]) #Reverse was True

	try:
		strOldestBackup = os.path.join(archiveDir, temp2[0][1])
	except IndexError: # an Index error means there is no backups in the directory.
		return 0
		
	return strOldestBackup
	
def CheckIfBackupsFull(numAllowedBackups, numExistingBackups, oldBackup):
	"""
	Checks if backup directory is fulland returns a bool. If its full it
	deletes the backup. Returns True if full and returns False if not full.
	"""
	if int(numAllowedBackups) <= int(numExistingBackups): # If full return True.
		logging.info("Max allowed backups reached.")
		logging.info("Removing oldest backup, " + oldBackup)
		os.remove(oldBackup)
		logging.info("Backup Removed.")
		return True
	else:
		logging.debug("Backup is not full.")
		return False
		
def buildArchiveName():
	game = lc.game
	time = getTime()
	archiveDir = lc.archiveDir
	archiveName = archiveDir + game + "-" + time
	return archiveName
	
	
	
def main():
	"""
	Starts the main loop.
	"""
	global numAllowedBackups
	
	while True:
		
		CheckIfBackupsFull(numAllowedBackups, NumExistingBackups(), OldestBackup())
		copyTempDir() # Creates a temp directory
		makeArchive() # Makes the archive
		cleanUp() # Deletes the temp directory
		sleep(int(convertHoursToSeconds()))
		#sleep(60) # Debug

#
src = lc.src
dst = src + "-temp"
archiveDir = lc.archiveDir
toIgnore = lc.toIgnore
archiveType = lc.archiveType
timeBetweenBackups = lc.timeBetweenBackups
numAllowedBackups = lc.maxAllowedBackups
#


if __name__ == '__main__':
	logging.basicConfig(level=logging.DEBUG, format='[%(levelname)s] %(asctime)s - %(threadName)-10s: %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')

	main()
